home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 1.iso / dist / fw_exmh.idb / usr / freeware / lib / exmh-2.5 / msg.tcl.z / msg.tcl
Text File  |  2002-07-08  |  19KB  |  746 lines

  1. # msg.tcl
  2. #
  3. # Operations on messages
  4. #
  5. # Copyright (c) 1993 Xerox Corporation.
  6. # Use and copying of this software and preparation of derivative works based
  7. # upon this software are permitted. Any distribution of this software or
  8. # derivative works must comply with all applicable United States export
  9. # control laws. This software is made available AS IS, and Xerox Corporation
  10. # makes no warranty about the software, its performance or its conformity to
  11. # any specification.
  12.  
  13. proc Msg_Init {} {
  14.     Preferences_Resource msg(tagnames) m_tagnames general
  15.     Preferences_Resource msg(tag,general) m_general {-relief flat}
  16.     Msg_Reset 0
  17. }
  18.  
  19. proc Msg_Reset { numMsgs {folder {}} } {
  20.     # Reset state after scanning a new folder
  21.     global msg
  22.     set msg(seen) {}            ;# list of seen messages
  23.     set msg(seenOld) {}            ;# seen, then deleted or moved
  24.     set msg(dpy)  {}            ;# Currently displayed message
  25.     set msg(id) [Mh_Cur $folder]    ;# pick current message
  26.     set msg(path) ""            ;# File pathname of current message
  27.     Buttons_Current [expr {$msg(id) != {}}]    ;# Enable/disable buttons
  28.     Ftoc_Reset $numMsgs $msg(id) $folder    ;# Reset display
  29. }
  30. proc Msg_CheckPoint {} {
  31.     # push current MH state to disk
  32.     global exmh msg
  33.     if {$msg(id) != ""} {
  34.     set cur $msg(id)
  35.     } else {
  36.     set cur ""
  37.     }
  38.     if {$cur != ""} {
  39.     Mh_SetCur $exmh(folder) $cur
  40.     } else {
  41.     Mh_ClearCur $exmh(folder)
  42.     }
  43.     if {$msg(seen) != {}} {
  44.     Mh_MarkSeen $exmh(folder) $msg(seen)
  45.     set msg(seen) {}
  46.     }
  47.     set msg(seenOld) {}
  48. }
  49. proc Msg_Pick { line {show show} } {
  50.     # Select a message
  51.     global exwin msg
  52.     Exmh_Debug Msg_Pick line=$line
  53.     set msgNum [Ftoc_MsgNumber $line]
  54.     if {$msgNum != {} && $msgNum != 0} {
  55.     Ftoc_RangeUnHighlight
  56.     Msg_Change $msgNum $show $line
  57.     } else {
  58.     Msg_ClearCurrent
  59.     }
  60. }
  61.  
  62. proc Msg_ShowCurrent { {show show} } {
  63.     global msg
  64.     if {$msg(id) != {}} {
  65.     set msg(dpy) {}    ;# force redisplay
  66.     Msg_Change $msg(id) $show
  67.     return 1
  68.     } else {
  69.     Msg_ClearCurrent
  70.     Ftoc_Yview end
  71.     return 0
  72.     }
  73. }
  74. proc Msg_ShowUnseen { {show show} } {
  75.     global exmh
  76.     foreach id [Flist_UnseenMsgs $exmh(folder)] {
  77.     if {![Ftoc_Marked $id]} {
  78.         Msg_Change $id show
  79.         return 1
  80.     }
  81.     }
  82.     Msg_ClearCurrent
  83.     return 0
  84. }
  85. proc Msg_ClearCurrent { } {
  86.     global msg exmh
  87.     set msg(id) {}        ;# Clear current message
  88.     set msg(dpy) {}        ;# and currently displayed message
  89.     Mh_ClearCur $exmh(folder)
  90.     MsgClear
  91.     Buttons_Current 0
  92.     Uri_ClearCurrent
  93. }
  94. proc MsgClear {} {
  95.     global exwin msg
  96.     Label_Message ""
  97.     set msg(dpy) {}
  98.     $exwin(mtext) configure -state normal
  99.     $exwin(mtext) delete 0.0 end
  100.     $exwin(mtext) configure -state disabled
  101.     Face_Delete
  102.     catch {destroy $exwin(mopButtons).list}
  103. }
  104. proc Msg_ShowSomething {} {
  105.     global exmh msg
  106.     set order {unseen cur}
  107.     foreach pick $order {
  108.     if {[catch {MhExec pick +$exmh(folder) $pick} tmp] == 0} then {
  109.         Msg_Change [lindex $tmp 0] show
  110.         return
  111.     }
  112.     }
  113.     # Hack
  114.     global ftoc
  115.     Msg_Pick $ftoc(numMsgs) show
  116. }
  117. proc Msg_ShowWhat { {what last} {show show} } {
  118.     if {$what == {}} {
  119.     Msg_ClearCurrent
  120.     return 0
  121.     } else {
  122.     Msg_Change {} $show $what
  123.     return 1
  124.     }
  125. }
  126. proc Msg_First { {show noshow} } {
  127.     Msg_Change {} $show first
  128. }
  129.  
  130. proc Msg_Last { {show noshow} } {
  131.     Msg_Change {} $show last
  132. }
  133.  
  134. proc Msg_Change {msgid {show show} {line {}} } {
  135.     Exmh_Debug Msg_Change id=$msgid line=$line
  136.     Exmh_Debug Msg_Change [time [list MsgChange $msgid $show $line]]
  137. }
  138. proc MsgChange {msgid {show show} {line {}} } {
  139.     global exmh exwin msg mhProfile
  140.  
  141.     if {$msgid != {}} {
  142.     # Allow null msgid from Msg_ShowWhat, which supplies line instead
  143.     if {$msgid < 0}  return
  144.     } else {
  145.         # line null too, try using first in folder
  146.         if {[string length $line] == 0} { set line 1 }
  147.     set msgid [Ftoc_MsgNumber [Ftoc_FindMsg $msgid $line]]
  148.     }
  149.     Ftoc_ClearCurrent
  150.     if {! [Ftoc_Change $msgid $line $show]} {
  151.     Exmh_Status "Cannot find msg $msgid - Rescan?"
  152.     } else {
  153.     if {$msg(id) == {}} {
  154.         Buttons_Current 1
  155.     }
  156.     set msg(id) $msgid
  157.     set msg(path) $mhProfile(path)/$exmh(folder)/$msg(id)
  158.     if {$show == "show"} {
  159.         MsgShow $msgid
  160.     } else {
  161.         MsgClear
  162.     }
  163.     if {$line != {}} {
  164.         Ftoc_MoveFeedback $msgid $line
  165.     }
  166.     }
  167.     Folder_CheckPointShared
  168. }
  169.  
  170. proc MsgSeen { msgid } {
  171.     # Suppress duplicates or else mark does the wrong thing.
  172.     global msg
  173.     if {[lsearch $msg(seen) $msgid] < 0} {
  174.     lappend msg(seen) $msgid
  175.     }
  176.     Flist_MsgSeen $msgid
  177.     Flag_MsgSeen
  178. }
  179. proc Msg_UnSeen { msgid } {
  180.     # We nuke deleted and moved messages from the seen list because
  181.     # marking them confuses MH.  However, we still need to remember
  182.     # them to properly maintain our unseen state in the presense of
  183.     # background Flist_FindUnseen calls.  Hence msg(seenOld)
  184.     global msg
  185.     set ix [lsearch $msg(seen) $msgid]
  186.     if {$ix >= 0} {
  187.     set msg(seen) [lreplace $msg(seen) $ix $ix]
  188.     if {[lsearch $msg(seenOld) $msgid] < 0} {
  189.         lappend msg(seenOld) $msgid
  190.     }
  191.     }
  192. }
  193. proc Msg_Seen {} {
  194.     global msg
  195.     return [concat $msg(seenOld) $msg(seen)]
  196. }
  197.  
  198.  
  199. # Message operations.
  200. # These take two forms of arguments.  The original form is a single
  201. # argument that is the name of a hook procedure.  The new form is
  202. # a set of arguments for the underlying MH command.  The distinction is
  203. # made by seeing if the argument is the name of a Tcl command, if
  204. # not it is assumed to be arguments to the MH command.
  205.  
  206. proc Msg_Compose { args } {
  207.     if {[string length $args] == 0} {
  208.     set args Mh_CompSetup
  209.     }
  210.     if {[string compare [info command $args] $args] == 0} {
  211.     # Old interface with hook procedure
  212.     if [catch {$args} err] {            ;# Setup draft msg
  213.         Exmh_Status "$args: $err" purple
  214.         return
  215.     }
  216.     } else {
  217.     if {![eval MsgComp $args]} {
  218.         return
  219.     }
  220.     }
  221.     Edit_Draft                    ;# Run the editor
  222. }
  223. proc Msg_CompUse {folder id} {
  224.     global mhProfile
  225.     if {[string compare $folder $mhProfile(draft-folder)] == 0} {
  226.     Mh_SetCur $mhProfile(draft-folder) $id
  227.     Msg_Compose $id -use
  228.     } else {
  229.     Msg_Compose +$folder $id
  230.     }
  231. }
  232. # Compose a message to a particular person
  233. proc Msg_CompTo {address args} {
  234.     eval {Msg_Mailto "mailto:$address"} $args
  235. }
  236.  
  237. # Compose a message based on a mailto URL
  238. proc Msg_Mailto {url args} {
  239.     global mhProfile
  240.     if {![eval MsgComp $args]} {
  241.     return
  242.     }
  243.     set draftID [Mh_Cur $mhProfile(draft-folder)]
  244.     if {$draftID == {}} {
  245.     return
  246.     }
  247.     # See RFC 2368 for mailto: URL syntax
  248.     regsub mailto: $url {} url
  249.     if [catch {
  250.     set path $mhProfile(path)/$mhProfile(draft-folder)/$draftID
  251.     set in [open $path]
  252.     set X [read $in]
  253.     close $in
  254.     if {[regexp -nocase {\?} $url]} {
  255.         regsub -nocase {.*\?} $url {} headers
  256.         foreach hdr [split $headers &] {
  257.         if {[regexp -nocase {body=} $hdr]} {
  258.             regsub -nocase {body=} $hdr {} body
  259.             set body [MsgDecodeURL $body]
  260.         } else {
  261.             regexp {(.*)=(.*)} $hdr {} hdr_name hdr_value
  262.             set hdr_name [string toupper [string range $hdr_name 0 0]][string tolower [string range $hdr_name 1 end]]
  263.             set hdr_value [MsgDecodeURL $hdr_value]
  264.             if {[string compare $hdr_name To] == 0} {
  265.             set to $hdr_value
  266.             }
  267.             if {![regsub -nocase "(^|\n)$hdr_name:\[^\n\]*\n" $X "\\1$hdr_name: $hdr_value\n" X]} {
  268.             set hend [string last "\n--" $X]
  269.             set X "[string range $X 0 $hend]$hdr_name: $hdr_value\n[string range $X [expr $hend + 1] end]"
  270.             }
  271.         }
  272.         }
  273.         regsub -nocase {\?.*} $url {} url
  274.     }
  275.     if [info exists body] {
  276.         append X "\n$body" 
  277.     }
  278.     set url [MsgDecodeURL $url]
  279.     if {[string length $url]>0} {
  280.         if [info exists to] {
  281.         regsub -nocase "(^|\n)to:\[^\n\]*\n" $X "\\1To: $url, $to\n" X
  282.         } else {
  283.         regsub -nocase "(^|\n)to:\[^\n\]*\n" $X "\\1To: $url\n" X
  284.         }
  285.     } else {
  286.         if [info exists to] {
  287.         regsub -nocase "(^|\n)to:\[^\n\]*\n" $X "\\1To: $to\n" X
  288.         }
  289.     }
  290.     set out [open $path w]
  291.     puts -nonewline $out $X
  292.     close $out
  293.     } err] {
  294.     Exmh_Status $err
  295.     return
  296.     }
  297.     Edit_Draft                    ;# Run the editor
  298. }
  299.  
  300. # Use current selection as To: header
  301. proc Msg_CompSel {args} {
  302.     global mhProfile
  303.     if {[catch {selection get} address]} {
  304.     Exmh_Status "Select an address for Msg_CompTo"
  305.     return
  306.     }
  307.     eval {Msg_CompTo $address} $args
  308. }
  309.  
  310. # General wrapper around comp
  311. proc MsgComp {args} {
  312.     # allow args to include $exmh(folder) $msg(id) $mhProfile(path)
  313.     global exmh msg mhProfile    
  314.     if [catch {
  315.     set ix [lsearch $args -form]
  316.     if {$ix < 0} {
  317.         if [file exists $mhProfile(path)/$exmh(folder)/components] {
  318.         lappend args -form $exmh(folder)/components
  319.         }
  320.     }
  321.     Exmh_Status "comp $args"
  322.     eval {MhExec comp -nowhatnowproc} $args
  323.     set exmh([Mh_Cur $mhProfile(draft-folder)],action) comp
  324.     } err] {
  325.     Exmh_Status "comp: $err"
  326.     return 0
  327.     }
  328.     return 1
  329. }
  330.  
  331. proc Msg_ReplyAll { } {
  332.     global nmh
  333.  
  334.     if {$nmh == 1} {
  335.     Msg_Reply -group
  336.     } else {
  337.     Msg_Reply -cc to -cc cc
  338.     }
  339. }
  340.  
  341. proc Msg_Reply { args } {
  342.     global exmh msg mhProfile
  343.     if {[string length $args] == 0} {
  344.     set args Mh_ReplySetup
  345.     }
  346.  
  347.     if [MsgOk $msg(id) m] {
  348.     Quote_MakeFile $exmh(folder) $m
  349.     set edit 1
  350.     if {[string compare [info command $args] $args] == 0} {
  351.         # Old interface with hook procedure
  352.         if [catch {$args $exmh(folder) $m} err] {    ;# Setup draft msg
  353.         Exmh_Status "${args}: $err" purple
  354.         Quote_Cleanup
  355.         return
  356.         }
  357.     } else {
  358.         Exmh_Status "repl $args" purple
  359.         if [catch {
  360.         set ix [lsearch $args -noedit]
  361.         if {$ix >= 0} {
  362.             set edit 0
  363.             set args [lreplace $args $ix $ix]
  364.         }
  365.         set ix [lsearch $args -form]
  366.         if {$ix < 0} {
  367.                     set path [Mh_FindFile "replcomps"]
  368.             if {0 != [string length $path]} {
  369.             lappend args -form $path/replcomps
  370.             Exmh_Status "repl $args" purple
  371.             }
  372.         }
  373.         eval {MhExec repl +$exmh(folder) $m -nowhatnowproc} $args
  374.         eval {MhAnnoSetup $exmh(folder) $m repl} $args
  375.         } err] {    ;# Setup draft msg
  376.         Exmh_Status "repl: $err" purple
  377.         Quote_Cleanup                ;# Nuke @ link
  378.         return
  379.         }
  380.     }
  381.     if {$edit} {
  382.         Edit_Draft                    ;# Run the editor
  383.     } else {
  384.         Edit_Done send                ;# Just send it
  385.     }
  386.    }
  387. }
  388.  
  389. proc Msg_Forward { args } {
  390.     global exmh msg mhProfile
  391.     if {[string length $args] == 0} {
  392.     set args Mh_ForwSetup
  393.     }
  394.  
  395.     set ids {}
  396.     Ftoc_Iterate line {
  397.     set msgid [Ftoc_MsgNumber $line]
  398.     if {$msgid != {}} {
  399.         lappend ids $msgid
  400.     }
  401.     }
  402.     if {[llength $ids] > 0} {
  403.     global mhProfile
  404.     set mime 0
  405.     if [info exists mhProfile(forw)] {
  406.         if {[lsearch $mhProfile(forw) -mime] >= 0} {
  407.         set mime 1
  408.         }
  409.     }
  410.     if {[string compare [info command $args] $args] == 0} {
  411.         # Old interface with hook procedure
  412.         if [catch {$args $exmh(folder) $ids} err] {    ;# Setup draft msg
  413.         Exmh_Status "${args}: $err" purple
  414.         return
  415.         }
  416.     }  else {
  417.         Exmh_Status "forw +$exmh(folder) $ids $args"
  418.         if [catch {
  419.         if {[lsearch $args -mime] >= 0} {
  420.             set mime 1
  421.         }
  422.         set ix [lsearch $args -form]
  423.         if {$ix < 0} {
  424.             if [file exists $mhProfile(path)/$exmh(folder)/forwcomps] {
  425.             lappend args -form $exmh(folder)/forwcomps
  426.             Exmh_Status "forw +$exmh(folder) $ids $args"
  427.             }
  428.         }
  429.         eval {MhExec forw +$exmh(folder)} $ids -nowhatnowproc $args
  430.         eval {MhAnnoSetup $exmh(folder) $ids forw} $args
  431.         if {$mhProfile(forwtweak)} {
  432.             Mh_Forw_MungeSubj $exmh(folder) $ids
  433.         }
  434.         } err] {
  435.         Exmh_Status "forw: $err" purple
  436.         return
  437.         }
  438.     }
  439.     # sedit hack
  440.     global sedit
  441.     set old $sedit(mhnDefault)
  442.     if {$mime} {set sedit(mhnDefault) 1}
  443.     Edit_Draft                    ;# Run the editor
  444.     set sedit(mhnDefault) $old
  445.    }
  446. }
  447.  
  448. proc Msg_Dist { args } {
  449.     global exmh msg
  450.     if {[string length $args] == 0} {
  451.     set args Mh_DistSetup
  452.     }
  453.  
  454.     if [MsgOk $msg(id) m] {
  455.     if {[string compare [info command $args] $args] == 0} {
  456.         # Old interface with hook procedure
  457.         if [catch {$args $exmh(folder) $m} err] {   ;# Setup draft msg
  458.         Exmh_Status "${args}: $err" purple
  459.         return
  460.         }
  461.     }  else {
  462.         if [catch {
  463.         Exmh_Status "dist +$exmh(folder) $m"
  464.         eval {MhExec dist +$exmh(folder) $m} -nowhatnowproc $args
  465.         eval {MhAnnoSetup $exmh(folder) $m dist} $args
  466.         } err] {
  467.         Exmh_Status "dist: $err" purple
  468.         return
  469.         }
  470.     }
  471.     Edit_Draft                                  ;# Run the editor
  472.     }
  473. }
  474.  
  475. proc MsgOk { number msgvar } {
  476.     upvar $msgvar msg
  477.     if {$number != ""} {
  478.     set msg $number
  479.     return 1
  480.     } else {
  481.     Exmh_Status "No valid message number" red
  482.     return 0
  483.     }
  484. }
  485.  
  486. proc Msg_Remove { {rmProc Ftoc_RemoveMark} {show show} } {
  487.     Exmh_Debug Msg_Remove $rmProc
  488.     Ftoc_Iterate line {
  489.     set msgid [Ftoc_MsgNumber $line]
  490.     Exmh_Debug Msg_Remove l=$line m=$msgid
  491.     $rmProc $line $msgid
  492.     }
  493.     if {[Ftoc_PickSize] == 1} {
  494.     Ftoc_NextImplied $show
  495.     }
  496. }
  497. proc Msg_RemoveNoshow { {rmProc Ftoc_RemoveMark} } {
  498.     Msg_Remove $rmProc noshow
  499. }
  500. proc Msg_RemoveById { msgid {rmProc Ftoc_Delete} } {
  501.     global msg
  502.     set line [Ftoc_FindMsg $msgid]
  503.     $rmProc $line $msgid
  504.     Msg_UnSeen $msgid
  505.     if {$msg(id) == $msgid} {
  506.     Msg_ClearCurrent
  507.     }
  508. }
  509. proc Msg_Move { {moveProc Ftoc_MoveMark} {advance 1} {show show} } {
  510.     global exmh fdisp
  511.  
  512.     if {$exmh(target) == ""} {
  513.     Exmh_Status "Must first click button $fdisp(tarbutton) on folder label to pick destination" purple
  514.     return
  515.     }
  516.     if { $exmh(target) != $exmh(folder)} then {
  517.     Ftoc_Iterate line {
  518.         set msgid [Ftoc_MsgNumber $line]
  519.         $moveProc $line $msgid
  520.     }
  521.     Exmh_Status "=> $exmh(target)"
  522.     if {[Ftoc_Advance $advance] && ([Ftoc_PickSize] == 1)} {
  523.         Ftoc_NextImplied $show
  524.     }
  525.     } else {
  526.     Exmh_Status "Move or copy requires target folder != current folder"
  527.     }
  528. }
  529. proc Msg_MoveNoshow { {moveProc Ftoc_MoveMark} } {
  530.     Msg_Move $moveProc 1 noshow
  531. }
  532. proc Msg_Clip { {folder {}}  {id {}} } {
  533.     # "Tear off" a message into a top-level text widget
  534.     global mhProfile exmh msg exwin
  535.  
  536.     if {$folder == {}} {set folder $exmh(folder)}
  537.     if {$id     == {}} {set id     $msg(id)}
  538.  
  539.     if {$id == {}} {
  540.     Exmh_Status "Select a message to clip first" red
  541.     return
  542.     }
  543.     if ![info exists msg(tearid)] {
  544.     set msg(tearid) 0
  545.     } else {
  546.     incr msg(tearid)
  547.     }
  548.     set self [Widget_Toplevel .tear$msg(tearid) "$folder $id" Clip]
  549.  
  550.     Widget_Frame $self but Menubar {top fill}
  551.     Widget_AddBut $self.but quit "Dismiss" [list destroy $self]
  552.     Widget_Label $self.but label {left fill} -text $folder/$id
  553.     set cursor [option get $self cursor Text]
  554.     set t [Widget_Text $self $exwin(mtextLines) -cursor $cursor -setgrid true]
  555.     Msg_Setup $t
  556.     if [MsgShowInText $t $mhProfile(path)/$folder/$id] {
  557.         foreach cmd [info commands Hook_MsgClip*] {
  558.             if [catch {$cmd $mhProfile(path)/$folder/$id $t} err] {
  559.                 SeditMsg $t "$cmd $err"
  560.             }
  561.         }
  562.     }
  563.  
  564. }
  565. proc Msg_FindMatch {L string} {
  566.     global exwin
  567.     return [FindTextMatch $exwin(mtext) $L $string]
  568. }
  569. proc Msg_BurstDigest {} {
  570.     global msg exmh mhProfile
  571.  
  572.     if {$msg(id) == {}} {
  573.     Exmh_Status "No message selected to burst" purple
  574.     return
  575.     }
  576.     if {[Ftoc_Changes "Burst Digest"] != 0} {
  577.     # Pending changes and no autoCommit
  578.     return
  579.     }
  580.  
  581.     Exmh_Status "Bursting message $msg(id) in $exmh(folder)..." blue
  582.  
  583.     # burst the digest; catch the output
  584.     if [catch { MhExec burst -verbose $msg(id) +$exmh(folder)} out] {
  585.     Exmh_Status "Error bursting digest: $out"
  586.     } else {
  587.     # burst OK, split up the output
  588.     set allids {}
  589.     foreach line [ split $out \n] {
  590.         #extract the new message number and save in $allids
  591.         if [regexp {of digest .* becomes message ([0-9]+)} $line match msgid] {
  592.         lappend allids $msgid
  593.         }
  594.     }
  595.     set allids [lsort -increasing -integer $allids]
  596.     # mark new messages as unread
  597.     Exmh_Debug burst created msgs $allids
  598.     if {$allids != {}} {
  599.         eval { MhExec mark +$exmh(folder) -sequence $mhProfile(unseen-sequence) } $allids
  600.     }
  601.     # rescan to pick them up, make sure Commit is done.
  602.     Background_Wait
  603.     Exmh_Status "Bursting message $msg(id) in $exmh(folder)...done" blue
  604.     Scan_FolderUpdate $exmh(folder)
  605.     if {$allids != {}} {
  606.         Msg_Change [lindex $allids 0]
  607.     } else {
  608.         Msg_ClearCurrent
  609.     }
  610.     }
  611. }
  612. proc Msg_Save {} {
  613.     global exmh mhProfile
  614.     set files {}
  615.     Ftoc_Iterate line {
  616.     set msgid [Ftoc_MsgNumber $line]
  617.     lappend files $mhProfile(path)/$exmh(folder)/$msgid
  618.     }
  619.  
  620.     set name [FSBox "Select file to create/append to:" ]
  621.     if {$name != {}} {
  622.     set exists [file exists $name]
  623.     if [catch {eval {exec cat} $files {>> $name}} err] {
  624.         Exmh_Status $err error
  625.     } else {
  626.         set plural [expr {([llength $files] > 1) ? "s" : ""}]
  627.         if {$exists} {
  628.         Exmh_Status "Message$plural appended to $name"
  629.         } else {
  630.         Exmh_Status "Message$plural stored in $name"
  631.         }
  632.     }
  633.     } else {
  634.     Exmh_Status "canceled"
  635.     }
  636. }
  637.  
  638. proc Msg_Edit {} {
  639.     global exmh msg editor
  640.     if {$msg(path) == ""} {
  641.     Exmh_Status "No current message"
  642.     return
  643.     }
  644.     Exmh_Status "Editing $exmh(folder)/$msg(id)"
  645.     #
  646.     # Hack because exmh-async isn't appropriate in this case.
  647.     #
  648.     if {$editor(sedit!)} {
  649.     set edittype sedit
  650.     } else {
  651.     set edittype prog
  652.     }
  653.     if [regsub {^([     ]*)exmh-async(.*)$} $editor($edittype) {\2} newprog] {
  654.     set cmd [split [join [string trimright $newprog "& \t"]]]
  655.     Exmh_Status "Starting $cmd ..." warn
  656.     if [catch {eval exec $cmd $msg(path) &} err] {
  657.         Exmh_Status $err error
  658.     }
  659.     } else {
  660.     if {$editor($edittype) == "sedit"} {
  661.         set exmh([SeditId $msg(path)],action) auto
  662.     }
  663.     EditStart $msg(path) $edittype
  664.     }
  665. }
  666.  
  667. proc Msg_UUdecode {} {
  668.     global exmh msg mhProfile
  669.     set name [FSBox "Select file to decode into:" ]
  670.     if {$name != {}} {
  671.     Mime_Uudecode $msg(path) $name
  672.     } else {
  673.     Exmh_Status "uudecode canceled"
  674.     }
  675. }
  676.  
  677. proc Msg_MarkUnseen {} {
  678.     global exmh
  679.     Msg_CheckPoint
  680.     Ftoc_Iterate line {
  681.     set msgid [Ftoc_MsgNumber $line]
  682.     Mh_MarkUnseen $exmh(folder) $msgid
  683.     }
  684.     Msg_ClearCurrent
  685.     Ftoc_ClearCurrent
  686.     Flist_ForgetUnseen $exmh(folder)
  687.     Ftoc_ShowUnseen $exmh(folder)
  688. }
  689.  
  690. proc Msg_ReplyHelp {} {
  691.     Help Reply "Defining Reply Buttons and Menu Entries"
  692. }
  693.  
  694. proc Msg_PageOrNext {} {
  695.     global exwin
  696.     Widget_TextPageOrNext $exwin(mtext) implied
  697. }
  698. proc Msg_PageOrNextCommit {} {
  699.     global exwin
  700.     Widget_TextPageOrNext $exwin(mtext) no
  701. }
  702. proc Msg_PageDown {} {
  703.     global exwin
  704.     Widget_TextPageDown $exwin(mtext)
  705. }
  706. proc Msg_PageUp {} {
  707.     global exwin
  708.     Widget_TextPageUp $exwin(mtext)
  709. }
  710. proc Msg_LineDown {} {
  711.     global exwin
  712.     Widget_TextLineDown $exwin(mtext)
  713. }
  714. proc Msg_LineUp {} {
  715.     global exwin
  716.     Widget_TextLineUp $exwin(mtext)
  717. }
  718. proc Msg_Top {} {
  719.     global exwin
  720.     Widget_TextTop $exwin(mtext)
  721. }
  722. proc Msg_Bottom {} {
  723.     global exwin
  724.     Widget_TextBottom $exwin(mtext)
  725. }
  726. proc Msg_CopySelection {} {
  727.     global exwin sedit
  728.     catch {set sedit(killbuf) [$exwin(mtext) get sel.first sel.last]}
  729. }
  730. proc Msg_Trash { {trashFolder TRASH} } {
  731.     Folder_TargetMove $trashFolder
  732. }
  733. proc MsgDecodeURL { url } {
  734.     regsub -all -nocase {%0a} $url {}   url
  735.     regsub -all -nocase {%0d} $url "\n" url
  736.     regsub -all         {%20} $url { }  url
  737.     regsub -all         {%25} $url {%}  url
  738.     regsub -all -nocase {%2c} $url {,}  url
  739.     regsub -all -nocase {%3c} $url {<}  url
  740.     regsub -all -nocase {%3d} $url {=}  url
  741.     regsub -all -nocase {%3e} $url {>}  url
  742.     regsub -all -nocase {%3f} $url {?}  url
  743.     return $url
  744. }
  745.  
  746.